package liming.ai.code.v4.core;

import liming.ai.code.v4.data.BaseConfig;
import liming.ai.client.impl.deepseek.DeepSeekClient;
import liming.ai.core.ResponseInterface;
import liming.ai.data.AbstractRequest;
import liming.ai.data.deepseek.Answer;
import liming.ai.data.deepseek.ChatCompletionRequest;
import liming.ai.data.deepseek.Message;
import liming.tool.file.FileRW;
import liming.tool.lock.CodeCondition;
import liming.tool.lock.CodeLock;
import liming.tool.runnable.HandRunnable;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.IOException;

public class QueryCore {
    private static DeepSeekClient deepSeekClient;
    static {
        try {
            deepSeekClient = new DeepSeekClient(new File("./config.json")){
                @Override
                public String chat(String question, ChatCompletionRequest request) {
                    CodeCondition condition = new CodeLock().newCondition();
                    Answer answer = new Answer(question);
                    request.addMessage(new Message(Message.Role.USER,question));
                    String q = question.replaceAll( "[\\\\/:*?\"<>|]","").replace("\n","");
                    String substring = System.currentTimeMillis()+"_"+q.substring(0,Math.min(q.length(),10));
                    HandRunnable.run(()->FileRW.writeTextFile(new File(file,substring+"_1_问题.txt"),question,false,config.getFileWriterEncoding()));
                    File file1 = new File(file, substring + "_2_思考.txt");
                    File file2 = new File(file, substring + "_3_回答.md");
                    core.handle(request, new ResponseInterface() {
                        @Override
                        public void onError(AbstractRequest request, String error) {
                            answer.setAnswer("出错了（OvO） "+error);
                            condition.signal();
                        }

                        int count = 0;
                        final String string = "....    ";

                        @Override
                        public void oneReasoningContent(String reasoningContent) {
                            HandRunnable.run(()-> FileRW.writeTextFile(file1,reasoningContent,true));
                            count++;
                            if(count>3)
                                count=0;
                            System.out.print("\r思考中"+string.substring(count,count+4));

                        }

                        @Override
                        public void oneContent(String content) {
                            HandRunnable.run(()-> FileRW.writeTextFile(file2,content,true));
                            count++;
                            if(count>3)
                                count=0;
                            System.out.print("\r处理中"+string.substring(count,count+4));
                        }

                        @Override
                        public void onComplete(String reasoningContent, String content) {
                            System.out.println("\n=======================================");
                            request.addMessage(new Message(Message.Role.ASSISTANT, content));
                            answer.setAnswer(content);
                            answer.setReasoning(reasoningContent);
                            condition.signal();
                        }
                    });
                    condition.await();
                    return answer.getAnswer();
                }
            };
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    public static String chat(String query, ChatCompletionRequest request){
        return deepSeekClient.chat(query, request);
    }

    public static ChatCompletionRequest newQueryRequest(){
        ChatCompletionRequest chatCompletionRequest = new ChatCompletionRequest();
        String message = String.format("你是一个资深java工程师，你需要根据用户提出的需求,设计大致方案。\n" +
                "限制条件:\n" +
                "- 项目分为java源文件、class编译文件、md简介文件3个部分，分别在项目根目录下的 %s、%s、%s 位置\n" +
                "- 对于一个类的java、class、md文件相对于对应的根目录的路径是一致的，即在知道全限制限定名时，可反推3种文件位置\n" +
                "- 在md中，包含类的基本信息以及作用、依赖关系，尽可能简单全面\n"+
                "- 包结构符合com.[项目].模块分层,如果提问中已包含包结构，则按实际所需来\n" +
                "- 在用户未给出开发环境时，默认使用jdk8进行原生开发，不使用数据库，即在未知的情况下，不采用额外的拓展\n" +
                "- 包含必要的字段和Javadoc\n" +
                "- 代码生成时，避免依赖循环，即C->B->A时，生成顺序为A-B-C，如果多个类之间发生相互依赖，则采用中间类的方式避免循环依赖导致编译不通过\n" +
                "- 在生成每个类的代码中加入静态的返回值为空的测试方法,如果不需要测试，则不加入test字段，用于判断功能是否可用，并给出测试方法名字，参数列表为空,如果不需要测试，则不加入test字段\n" +
                "- 如果未给定版本version的情况下，version默认为1，在已知版本的情况下，生成的版本要比已知版本+1，" +
                "如已知A1、B2、C1,在生成C1时发现需要重新生成A1、B2,此时给出的版本号为A2、B3、C2,如果仅需重构AB中的一个，则生成A2或者B3，以及C2\n" +
                "- 严格返回以下JSON格式的内容：" +
                "{\n" +
                "       \"classes\": [" +
                "           {\n" +
                "               \"package\": \"包路径\",\n" +
                "               \"name\": \"类名\",\n" +
                "               \"code\": \"package ...开始，包含导入的其他类，详细代码\",\n"+
                "               \"test\": \"方法名\",\n" +
                "               \"version\": \"当前版本\"\n" +
                "           }\n" +
                "       ]\n" +
                "   }\n" +
                "在classes按依赖顺序输出\n" +
                "- 在test、md、code中采用单行展示，及所需的换行符使用转译\\包裹", BaseConfig.JAVAS_PATH,BaseConfig.CLASSES_PATH,BaseConfig.MDS_FILE_PATH);
        chatCompletionRequest.addMessage(new Message(Message.Role.SYSTEM,message));
        return chatCompletionRequest;
    }
    public static ChatCompletionRequest newCodeRequest(){
        ChatCompletionRequest chatCompletionRequest = new ChatCompletionRequest();
        String message = String.format("你是一个资深java工程师，你需要根据用户提出的问题,制定解决方法。\n" +
                "限制条件:\n" +
                "- 项目分为java源文件、class编译文件、md简介文件3个部分，分别在项目根目录下的 %s、%s、%s 位置，" +
                "对一个类需要生成源码及其md介绍文档\n" +
                "- 对于一个类的java、class、md文件相对于对应的根目录的路径是一致的，即在知道全限制限定名时，可反推3种文件位置\n" +
                "- 在md中，包含类的基本信息以及作用、依赖关系，尽可能简单全面\n"+
                "- 包结构符合com.[项目].模块分层,如果提问中已包含包结构，则按实际所需来\n" +
                "- 在用户未给出开发环境时，默认使用jdk8进行原生开发，不使用数据库，即在未知的情况下，不采用额外的拓展\n" +
                "- 包含必要的字段和Javadoc\n" +
                "- 代码生成时，避免依赖循环，即C->B->A时，生成顺序为A-B-C，如果多个类之间发生相互依赖，则采用中间类的方式避免循环依赖导致编译不通过\n" +
                "- 在用户提交问题后，根据用户提交的内容，思考当前已知条件是否齐全，" +
                "比如在生成B生成需要A，此时可以通过用户提供的文件路径（全限定名、java、class、md之一）获取A的信息（优先md，如果md无法满足则获取java)，" +
                "如果生成B时，没有提供A的信息，说明A没有写入编译生成，此时需要同时给出A的完整代码\n" +
                "- 在生成每个类的代码中加入静态的返回值为空的测试方法,如果不需要测试，并给出测试方法名字，参数列表为空,如果不需要测试，则不加入test字段\n" +
                "- 返回类型为json格式\n" +
                "- 如果未给定版本version的情况下，version默认为1，在已知版本的情况下，生成的版本要比已知版本+1，" +
                "如已知A1、B2、C1,在生成C1时发现需要重新生成A1、B2,此时给出的版本号为A2、B3、C2,如果仅需重构AB中的一个，则生成A2或者B3，以及C2\n" +
                "- 如果需要文件支持,则其返回格式为{\"files\":[\"路径1\",\"路径2\"]}，其中一组类信息只能出现一次（全限定名、java、class、md为一组）" +
                "（出现一次的意思是：假如有A类，那么在返回文件路径中，只能出现一组路径四个中的一个，不能同时出现2个及以上的路径，但不同组的同类型文件可以同时存在）\n" +
                "- 如果不需要文件支持了，则严格返回以下JSON格式的内容：" +
                "{\n" +
                "       \"classes\": [" +
                "           {\n" +
                "               \"package\": \"包路径\",\n" +
                "               \"name\": \"类名\",\n" +
                "               \"code\": \"package ...开始，包含导入的其他类，完整代码\",\n" +
                "               \"md\": \"md格式介绍，包含当前类所有对外的api介绍\"\n" +
                "               \"test\": \"方法名\",\n" +
                "               \"version\": \"本次版本\"\n" +
                "           }\n" +
                "       ]\n" +
                "   }\n" +
                "在classes按依赖顺序输出\n" +
                "- 在test、md、code中采用单行展示，及所需的换行符使用转译\\包裹", BaseConfig.JAVAS_PATH,BaseConfig.CLASSES_PATH,BaseConfig.MDS_FILE_PATH);
        chatCompletionRequest.addMessage(new Message(Message.Role.SYSTEM,message));
        return chatCompletionRequest;
    }

    public static JSONObject valueOf(String json){
//        json=json.replace("\n","");
        int start = json.indexOf("{");
        int end = json.lastIndexOf("}") + 1;
        String substring = json.substring(start, end);
        try {
            return new JSONObject(substring);
        }catch (JSONException e){
            ChatCompletionRequest chatCompletionRequest = new ChatCompletionRequest();
            chatCompletionRequest.addMessage(new Message(Message.Role.SYSTEM,"你是一个ai助手，负责处理json格式问题"));
            String query = String.format("异常:\n%s\n" +
                            "原本内容为:\n%s\n" +
                            "给出修改格式后的内容，使其能处理"
            ,FileRW.getStackTrace(e),json);
            return valueOf(QueryCore.chat(query,chatCompletionRequest));
        }
    }
}
